<template>
  <div class="code-generator">
    <!-- 左侧画布区域 -->
    <div class="canvas-container">
      <div 
        class="canvas-area" 
        @dragover.prevent="handleDragOver($event)"
        @drop.prevent="handleDrop($event)"
        @click.self="selectCanvas($event)"
        ref="canvasRef"
        :style="{
          backgroundColor: canvasConfig.backgroundColor,
          backgroundImage: getBackgroundImage(),
          backgroundRepeat: 'repeat, repeat',
          backgroundPosition: canvasConfig.gridVisible ? '0 0, 0 0' : '0 0',
          backgroundSize: canvasConfig.gridVisible ? '20px 20px, 20px 20px' : 'cover'
        }"
      >
        <div 
          v-show="dragGuideLines.visible" 
          class="drag-guide-line vertical"
          :style="{
            transform: `translateX(${dragGuideLines.x}px)`
          }"
        ></div>
        <div 
          v-show="dragGuideLines.visible" 
          class="drag-guide-line horizontal"
          :style="{
            transform: `translateY(${dragGuideLines.y}px)`
          }"
        ></div>
        <div 
          v-show="gridHighlight.visible && canvasConfig.gridVisible" 
          class="grid-highlight"
          :style="{
            transform: `translate(${gridHighlight.x}px, ${gridHighlight.y}px)`
          }"
        ></div>
        <div
          v-for="(item, index) in canvasItems"
          :key="index"
          :style="item.style"
          class="canvas-item"
          @click="selectItem(index)"
          draggable="true"
          @dragstart="handleItemDragStart(index, $event)"
          @dragend="handleItemDragEnd($event)"
        >
          <component 
            :is="item.component"
            :config="item.config"
          ></component>
          <div class="item-actions">
            <button @click.stop="deleteItem(index)" class="delete-btn">×</button>
          </div>
        </div>
        <template v-if="snapConfig.guidelines.length > 0">
          <div
            v-for="(guideline, index) in snapConfig.guidelines"
            :key="index"
            class="snap-guideline"
            :class="{ 
              'vertical': guideline.type === 'left' || guideline.type === 'right' || guideline.type === 'center',
              'horizontal': guideline.type === 'top' || guideline.type === 'bottom' || guideline.type === 'center'
            }"
            :style="{
              [guideline.type === 'left' || guideline.type === 'right' || guideline.type === 'center' ? 'left' : 'top']: `${guideline.pos}px`
            }"
          ></div>
        </template>
      </div>
    </div>

    <!-- 右侧面板 -->
    <div class="control-panel">
      <!-- 组件列表 -->
      <div class="components-list">
        <h3>组件列表</h3>
        <div
          v-for="(comp, index) in componentsList"
          :key="index"
          class="component-item"
          draggable="true"
          @dragstart="handleDragStart(comp, $event)"
        >
          <span class="comp-icon">{{ comp.icon }}</span>
          <span>{{ comp.label }}</span>
        </div>
      </div>

      <!-- 属性面板 -->
      <div v-if="selectedIndex !== null" class="properties-panel">
        <h3>组件配置</h3>
        
        <!-- 基础样式配置 -->
        <BaseStyleConfig
          :style="canvasItems[selectedIndex].style"
          @update:style="updateItemStyle"
        />

        <!-- 组件特定配置 -->
        <component 
          :is="`${canvasItems[selectedIndex].component}Config`"
          v-if="canvasItems[selectedIndex].config"
          :config="canvasItems[selectedIndex].config"
          @update:config="updateComponentConfig"
        />
      </div>

      <!-- 新增：画布配置面板 -->
      <div v-if="isCanvasSelected" class="properties-panel">
        <h3>画布配置</h3>
        <CanvasConfig
          :config="canvasConfig"
          @update:config="updateCanvasConfig"
          @download-canvas="downloadCanvas"
        />
      </div>

      <!-- 代码预览 -->
      <div class="code-preview">
        <button @click="showCodePreview" class="preview-btn">
          <span class="btn-icon">📋</span>
          预览代码
        </button>
      </div>
    </div>

    <!-- 添加代码预览弹窗 -->
    <div v-if="showPreview" class="modal-overlay" @click="closePreview">
      <div class="modal-content" @click.stop>
        <div class="modal-header">
          <h3>代码预览</h3>
          <button class="close-btn" @click="closePreview">×</button>
        </div>
        <div class="modal-body markdown-body">
          <MdPreview 
            :modelValue="generatedCode" 
            :theme="previewTheme"
            :preview-theme="previewTheme"
            :code-theme="codeTheme"
            preview-only
            class="md-preview"
            :expand="true"
            :showCodeRowNumber="true"
            codeStyleReverse
            :noMermaid="true"
          />
        </div>
        <div class="modal-footer">
          <button class="copy-btn" @click="copyCode">
            <span class="btn-icon">{{ copied ? '✓' : '📋' }}</span>
            {{ copied ? '已复制' : '复制代码' }}
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import CommonHeader from './components/CommonHeader.vue'
import CommonTitle from './components/CommonTitle.vue'
import CommonChart from './components/CommonChart.vue'
import CommonTable from './components/CommonTable.vue'
import CommonForm from './components/CommonForm.vue'
import CommonCard from './components/CommonCard.vue'
import BaseStyleConfig from './components/configs/BaseStyleConfig.vue'
import CommonHeaderConfig from './components/configs/CommonHeaderConfig.vue'
import CommonTitleConfig from './components/configs/CommonTitleConfig.vue'
import CanvasConfig from './components/configs/CanvasConfig.vue'
import CommonFooter from './components/CommonFooter.vue'
import CommonFooterConfig from './components/configs/CommonFooterConfig.vue'
import CommonChartConfig from './components/configs/CommonChartConfig.vue'
import { MdPreview } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
import 'md-editor-v3/lib/preview.css';
import hljs from 'highlight.js';
import 'highlight.js/styles/vs2015.css';
import html2canvas from 'html2canvas';
import PieChart from './components/PieChart.vue'
import PieChartConfig from './components/configs/PieChartConfig.vue'

export default {
  name: 'CodeGenerator',
  data() {
    return {
      componentsList: [
        { label: '公共头部', component: 'CommonHeader', icon: '🎯' },
        { label: '公共标题', component: 'CommonTitle', icon: '📝' },
        { 
          label: '图表组件', 
          component: 'CommonChart', 
          icon: '📊',
          defaultConfig: {
            width: '690px',
            height: '300px',
            backgroundColor: '#ffffff',
            option: {
              title: {
                text: '图表标题'
              },
              tooltip: {
                trigger: 'axis'
              },
              legend: {
                show: true,
                orient: 'horizontal',
                top: '5%',
                left: 'center',
                textStyle: {
                  color: '#333',
                  fontSize: 12
                },
                itemWidth: 25,
                itemHeight: 14,
                itemGap: 10,
                selectedMode: 'multiple'
              },
              xAxis: {
                show: true,
                type: 'category',
                data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
                name: '',
                axisLabel: {
                  show: true,
                  color: '#333',
                  fontSize: 12
                },
                axisLine: {
                  show: true,
                  lineStyle: {
                    color: '#333'
                  }
                },
                axisTick: {
                  show: true
                }
              },
              yAxis: {
                show: true,
                type: 'value',
                name: '',
                axisLabel: {
                  show: true,
                  color: '#333',
                  fontSize: 12
                },
                axisLine: {
                  show: true,
                  lineStyle: {
                    color: '#333'
                  }
                },
                axisTick: {
                  show: true
                },
                splitLine: {
                  show: true,
                  lineStyle: {
                    color: '#eee'
                  }
                }
              },
              series: [{
                name: '数据系列1',
                type: 'line',
                data: [150, 230, 224, 218, 135, 147, 260],
                itemStyle: {
                  color: '#5470c6'
                },
                lineStyle: {
                  width: 2
                }
              }]
            }
          }
        },
        { label: '表组件', component: 'CommonTable', icon: '📋' },
        { label: '表单组件', component: 'CommonForm', icon: '📑' },
        { label: '卡片组件', component: 'CommonCard', icon: '🗂' },
        { label: '公共尾部', component: 'CommonFooter', icon: '🔻' },
        { 
          label: '饼图组件', 
          component: 'PieChart', 
          icon: '🥧',
          defaultConfig: {
            width: '690px',
            height: '300px',
            backgroundColor: '#093443',
            option: {
              tooltip: {
                trigger: 'item',
                formatter: '{a} <br/>{b}: {c} ({d}%)'
              },
              legend: {
                show: true,
                orient: 'horizontal',
                top: '5%',
                left: 'center',
                textStyle: {
                  color: '#fff',
                  fontSize: 12
                }
              },
              series: [{
                name: '饼图数据',
                type: 'pie',
                radius: ['0%', '70%'],
                center: ['50%', '50%'],
                roseType: false,
                label: {
                  show: true,
                  position: 'outside',
                  formatter: '{b}: {d}%',
                  color: '#fff'
                },
                data: [
                  { name: '数据1', value: 335, itemStyle: { color: '#5470c6' } },
                  { name: '数据2', value: 234, itemStyle: { color: '#91cc75' } },
                  { name: '数据3', value: 158, itemStyle: { color: '#fac858' } }
                ]
              }]
            }
          }
        }
      ],
      canvasItems: [],
      selectedIndex: null,
      draggedItemIndex: null,
      generatedCode: '',
      defaultStyle: {
        position: 'absolute',
        width: '200px',
        height: '100px',
        borderRadius: '4px',
        border: '1px solid transparent',
        boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
      },
      canvasRef: null,
      canvasBounds: {
        width: 1200,
        height: 800
      },
      showPreview: false,
      copied: false,
      canvasConfig: {
        backgroundColor: '#053043',
        backgroundImage: '',
        gridVisible: true,
      },
      isCanvasSelected: false,
      previewTheme: 'github',
      codeTheme: 'github',
      dragGuideLines: {
        x: 0,
        y: 0,
        visible: false
      },
      gridHighlight: {
        x: 0,
        y: 0,
        visible: false
      },
      snapConfig: {
        threshold: 5, // 吸附阈值（像素）
        guidelines: [], // 存储对齐参考线
        isSnapping: false,
      }
    }
  },
  components: {
    CommonHeader,
    CommonTitle,
    CommonChart,
    CommonTable,
    CommonForm,
    CommonCard,
    BaseStyleConfig,
    CommonHeaderConfig,
    CommonTitleConfig,
    CanvasConfig,
    CommonFooter,
    CommonFooterConfig,
    CommonChartConfig,
    MdPreview,
    PieChart,
    PieChartConfig
  },
  mounted() {
    this.canvasRef = this.$refs.canvasRef
  },
  methods: {
    handleDragStart(comp) {
      const dragEvent = window.event || event
      dragEvent.dataTransfer.setData('application/json', JSON.stringify(comp))
      dragEvent.dataTransfer.effectAllowed = 'copy'
    },
    handleDrop(event) {
      try {
        const canvasRect = this.canvasRef.getBoundingClientRect()
        const scaleMatch = this.canvasRef.style.transform.match(/scale\((.*?)\)/)
        const scale = scaleMatch ? parseFloat(scaleMatch[1]) : 1

        let x = (event.clientX - canvasRect.left) / scale
        let y = (event.clientY - canvasRect.top) / scale

        const dataStr = event.dataTransfer.getData('application/json')
        if (!dataStr) {
          console.warn('No drag data found')
          return
        }

        const compData = JSON.parse(dataStr)
        if (!compData) return

        // 获取组件的默认配置
        const defaultConfig = this.getDefaultConfig(compData.component)

        // 如果是公共头部或尾部组件，强制设置位置
        if (compData.component === 'CommonHeader') {
          x = 0
          y = 0
        } else if (compData.component === 'CommonFooter') {
          x = 0
          y = 1080 - parseInt(defaultConfig.height)
        }

        // 创建样式象
        const styleObject = {
          ...this.defaultStyle,
          left: `${x}px`,
          ...(compData.component === 'CommonFooter' 
            ? { bottom: '0px', position: 'absolute' }
            : { top: `${y}px` }
          ),
          width: ['CommonHeader', 'CommonFooter'].includes(compData.component) 
            ? '100%' 
            : (defaultConfig.width || '200px'),
          height: compData.component === 'CommonHeader' 
            ? '100px' 
            : compData.component === 'CommonFooter' 
              ? defaultConfig.height 
              : (defaultConfig.height || '100px'),
          zIndex: defaultConfig.zIndex || 0
        }

        this.canvasItems.push({
          component: compData.component,
          style: styleObject,
          config: defaultConfig,
          events: {
            'update:config': (newConfig) => {
              // 找到当前组件的索引
              const index = this.canvasItems.findIndex(item => 
                item.component === compData.component && 
                item.config === this.selectedItem?.config
              )
              if (index !== -1) {
                // 更新配置
                this.canvasItems[index].config = { ...newConfig }
                // 如果是选中的组件，也更新选中的组件
                if (this.selectedIndex === index) {
                  this.selectedItem = this.canvasItems[index]
                }
                // 强制更新视图
                this.$forceUpdate()
              }
              console.log('Config updated:', newConfig)
            },
            'tab-change': (tabInfo) => {
              console.log('Tab changed:', tabInfo)
              
              // 可以根据 tabInfo 来处理联动
              if (tabInfo.identifier === 'title-tab-change') {
                // 这里可以处其他组件的联动
                this.handleTabChange(tabInfo)
              }
            }
          }
        })
        this.generateCode()
      } catch (error) {
        console.error('Drop handling error:', error)
      }
    },
    handleItemDragStart(index, event) {
      this.draggedItemIndex = index;
      event.dataTransfer.setData('text/plain', index.toString());
      event.dataTransfer.effectAllowed = 'move';
      event.target.style.opacity = '0.5';
      
      const canvasRect = this.canvasRef.getBoundingClientRect();
      const scale = this.getCanvasScale();
      
      // 计算初始辅助线位置
      this.dragGuideLines.x = (event.clientX - canvasRect.left) / scale;
      this.dragGuideLines.y = (event.clientY - canvasRect.top) / scale;
      this.dragGuideLines.visible = true;
    },
    handleItemDragEnd(event) {
      if (this.draggedItemIndex !== null && this.canvasRef) {
        const canvasRect = this.canvasRef.getBoundingClientRect();
        const scale = this.getCanvasScale();

        // 计算最终位置
        let x = (event.clientX - canvasRect.left) / scale;
        let y = (event.clientY - canvasRect.top) / scale;

        const currentItem = this.canvasItems[this.draggedItemIndex];
        if (!currentItem) return;

        // 恢复透明度
        event.target.style.opacity = '1';

        // 如果是头部或尾部组件，限制其位置
        if (currentItem.component === 'CommonHeader') {
          x = 0;
          y = 0;
        } else if (currentItem.component === 'CommonFooter') {
          x = 0;
          y = 1080 - parseInt(currentItem.style.height);
        } else {
          // 其他组件确保不超出边界
          x = Math.max(0, Math.min(x, 1920 - parseInt(currentItem.style.width)));
          y = Math.max(0, Math.min(y, 1080 - parseInt(currentItem.style.height)));
        }

        // 更新组件位置
        this.canvasItems[this.draggedItemIndex].style = {
          ...this.canvasItems[this.draggedItemIndex].style,
          left: `${x}px`,
          ...(currentItem.component === 'CommonFooter' 
            ? { bottom: '0px', position: 'absolute' }
            : { top: `${y}px` }
          )
        };

        // 重置状态
        this.draggedItemIndex = null;
        this.dragGuideLines.visible = false;
        this.gridHighlight.visible = false;
        this.snapConfig.isSnapping = false;
        this.snapConfig.guidelines = [];
        
        // 生成代码
        this.generateCode();
      }
    },
    selectItem(index) {
      this.selectedIndex = index
    },
    deleteItem(index) {
      this.canvasItems.splice(index, 1)
      if (this.selectedIndex === index) {
        this.selectedIndex = null
      }
      this.generateCode()
    },
    updateStyle() {
      this.$forceUpdate()
      this.generateCode()
    },
    generateCode() {
      // 添加调试打印
      console.log('Canvas Items:', this.canvasItems);
      
      // 收集所有需要放入 data 的据
      const dataProperties = {};
      
      let code = '';
      
      // 添加模板部分
      code += '<template>\n';
      code += '  <div class="generated-container" :style="containerStyle">\n';
      
      // 生成组件代码
      this.canvasItems.forEach((item, index) => {
        const componentName = item.component;
        if (componentName === 'CommonChart') {
          console.log('Chart Config:', item.config); // 打印图表置
          console.log('Data Source Type:', item.config.dataSourceType); // 打印数据源类型
          console.log('API Config:', item.config.apiConfig); // 打印 API 配置
          
          code += `    <${componentName}\n`;
          code += `      :style="component${index}Style"\n`;
          code += `      :config="chartConfig${index}"\n`;
          
          // 检查是否存在远程数据配置
          if (item.config.dataSourceType === 'api' && item.config.apiConfig) {
            console.log('Generating API config code'); // 打印生成 API 配置代码的标记
            code += `      :apiObj="{\n`;
            code += `        url: '${item.config.apiConfig.url}',\n`;
            code += `        method: '${item.config.apiConfig.method}',\n`;
            code += `        autoRefresh: ${item.config.apiConfig.autoRefresh},\n`;
            code += `        refreshInterval: ${item.config.apiConfig.refreshInterval},\n`;
            code += `        mapping: {\n`;
            code += `          categories: '${item.config.apiConfig.mapping.categories}',\n`;
            code += `          series: '${item.config.apiConfig.mapping.series}'\n`;
            code += `        }\n`;
            code += `      }"\n`;
          }
          
          code += `      ref="chart${index}"\n`;
          code += `    />\n`;

          // 将配置添加到 data 中
          dataProperties[`chartConfig${index}`] = { ...item.config };
          console.log('Generated Data Properties:', dataProperties); // 打印生成的数据属性
        } else {
          // 其他组件保持原有的代码生成逻辑
          code += `    <${componentName}\n`;
          code += `      :style="component${index}Style"\n`;
          
          // 处理配置性
          if (item.config) {
            Object.entries(item.config).forEach(([key, value]) => {
              if (Array.isArray(value) || (typeof value === 'object' && value !== null)) {
                const propName = `${componentName.charAt(0).toLowerCase() + componentName.slice(1)}${key.charAt(0).toUpperCase() + key.slice(1)}`;
                dataProperties[propName] = value;
                code += `      :${key}="${propName}"\n`;
              } else {
                // 对于字符串类型的值，检查是需要转换单位或处理路径
                if (typeof value === 'string') {
                  if (value.endsWith('px')) {
                    const convertedValue = this.convertConfigUnits({ [key]: value })[key];
                    code += `      :${key}="'${convertedValue}'"\n`;
                  } else if (value.includes('/blog/src/assets/')) {
                    const convertedValue = value.replace('/blog/', '');
                    code += `      :${key}="'${convertedValue}'"\n`;
                  } else {
                    code += `      :${key}="'${value}'"\n`;
                  }
                } else {
                  code += `      :${key}="'${value}'"\n`;
                }
              }
            });
          }
          
          code += '    />\n';
          
          // 将组件式放入 data
          dataProperties[`component${index}Style`] = this.convertStyleUnits(item.style);
        }
      });
      
      // 关闭模板
      code += '  </div>\n';
      code += '</template>\n\n';
      
      // 添加脚本部分
      code += '<script>\n';
      
      // 导入组件
      const uniqueComponents = [...new Set(this.canvasItems.map(item => item.component))];
      uniqueComponents.forEach(component => {
        code += `import ${component} from './components/${component}.vue';\n`;
      });
      
      code += '\nexport default {\n';
      code += '  name: \'GeneratedView\',\n';
      code += '  components: {\n';
      code += '    ' + uniqueComponents.join(',\n    ') + '\n';
      code += '  },\n';
      code += '  data() {\n';
      code += '    return {\n';
      
      // 加容器式
      code += '      containerStyle: {\n';
      code += `        backgroundColor: '${this.canvasConfig.backgroundColor}'`;
      if (this.canvasConfig.backgroundImage) {
        code += `,\n        backgroundImage: 'url(${this.canvasConfig.backgroundImage})',\n`;
        code += '        backgroundRepeat: \'no-repeat\',\n';
        code += '        backgroundSize: \'cover\'\n';
      }
      code += '      },\n';
      
      // 添加其他数据属性
      Object.entries(dataProperties).forEach(([key, value], index, array) => {
        code += `      ${key}: ${JSON.stringify(value)}`;
        code += index < array.length - 1 ? ',\n' : '\n';
      });
      
      // 关闭脚本
      code += '    }\n';
      code += '  }\n';
      code += '};\n';
      code += '</' + 'script>\n\n';
      
      // 添加样式
      code += '<style scoped>\n';
      code += '.generated-container {\n';
      code += '  width: 100%;\n';
      code += '  height: 100vh;\n';
      code += '  position: relative;\n';
      code += '  overflow: hidden;\n';
      code += '}\n';
      code += '</style>\n';
      
      this.generatedCode = "```vue\n" + code + "\n```";
    },
    convertStyleUnits(style) {
      const convertedStyle = { ...style };
      const canvasWidth = 1920;
      const canvasHeight = 1080;

      // 遍历所有样式属性
      Object.entries(convertedStyle).forEach(([key, value]) => {
        if (typeof value === 'string' && value.endsWith('px')) {
          const numValue = parseFloat(value);
          // 水平方向的属性使用 vw
          if (['width', 'left', 'right', 'margin-left', 'margin-right', 'padding-left', 'padding-right'].includes(key)) {
            convertedStyle[key] = `${(numValue / canvasWidth * 100).toFixed(2)}vw`;
          }
          // 垂直方向的属性使用 vh
          else if (['height', 'top', 'bottom', 'margin-top', 'margin-bottom', 'padding-top', 'padding-bottom'].includes(key)) {
            convertedStyle[key] = `${(numValue / canvasHeight * 100).toFixed(2)}vh`;
          }
          // 字体大小使用 vw
          else if (key === 'fontSize' || key === 'font-size') {
            convertedStyle[key] = `${(numValue / canvasWidth * 100).toFixed(2)}vw`;
          }
        }
      });

      return convertedStyle;
    },
    showCodePreview() {
      this.generateCode()
      this.showPreview = true
      this.copied = false
      // 禁止背景滚动
      document.body.style.overflow = 'hidden'
    },
    closePreview() {
      this.showPreview = false
      // 恢复景滚动
      document.body.style.overflow = 'auto'
    },
    async copyCode() {
      try {
        // 去除 markdown 格式，只复制实际代码
        const codeOnly = this.generatedCode.replace(/```vue\n/, '').replace(/\n```$/, '');
        await navigator.clipboard.writeText(codeOnly);
        this.copied = true;
        setTimeout(() => {
          this.copied = false;
        }, 2000);
      } catch (err) {
        console.error('Failed to copy code:', err);
      }
    },
    // 获取组件默认配置
    getDefaultConfig(componentName) {
      const configs = {
        CommonHeader: {
          text: '大屏页面配置平台',
          fontSize: '60px',
          fontWeight: 'normal',
          fontFamily: 'YouSheBiaoTiHei',
          letterSpacing: '10px',
          color: '#ffffff',
          backgroundImage: require('@/assets/images/header-bg.png'),
          backgroundColor: '#ffffff',
          zIndex: 1
        },
        CommonTitle: {
          title: '标题文本',
          color: '#ffffff',
          fontSize: '18px',
          width: '690px',
          height: '40px',
          backgroundImage: require('@/assets/images/headerTitlebg.png'),
          zIndex: 1,
          showTabs: false,
          tabItems: [
            { label: '选项一', value: 'tab1' },
            { label: '选项二', value: 'tab2' },
            { label: '选项三', value: 'tab3' }
          ],
          selectedTab: 'tab1',
          tabTextColor: '#ffffff',
          tabActiveTextColor: '#ffffff',
          tabFontSize: '14px',
          tabBackgroundImage: require('@/assets/images/tab-bg.png'),        // 公共默认背景
          tabActiveBackgroundImage: require('@/assets/images/tab-bg-active.png'),  // 公共选中背景
          tabWidth: '80px',
          tabHeight: '40px',
        },
        CommonChart: {
          width: '690px',
          height: '300px',
          backgroundColor: '#093443',
          dataSourceType: 'static',
          apiConfig: {
            url: '',
            method: 'GET',
            autoRefresh: false,
            refreshInterval: 10,
            mapping: {
              categories: 'data.categories',
              series: 'data.series'
            }
          },
          option: {
            title: {
              text: ''
            },
            tooltip: {
              trigger: 'axis'
            },
            legend: {
              show: true,
              orient: 'horizontal',
              top: '5%',
              left: 'center',
              textStyle: {
                color: '#fff',
                fontSize: 12
              },
              itemWidth: 25,
              itemHeight: 14,
              itemGap: 10,
              selectedMode: 'multiple',
              type: 'plain',
              selected: {}
            },
            xAxis: {
              show: true,
              type: 'category',
              data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
              name: '',
              axisLabel: {
                show: true,
                color: '#fff',
                fontSize: 14
              },
              axisLine: {
                show: true,
                lineStyle: {
                  color: 'rgba(56, 116, 139, 1)'
                }
              },
              axisTick: {
                show: false
              }
            },
            yAxis: {
              show: true,
              type: 'value',
              name: '',
              axisLabel: {
                show: true,
                color: '#CCEAFF',
                fontSize: 14
              },
              axisLine: {
                show: true,
                lineStyle: {
                  color: 'rgba(56, 116, 139, 1)'
                }
              },
              axisTick: {
                show: false
              },
              splitLine: {
                show: true,
                type: 'dashed',
                lineStyle: {
                  color: '#0B4F65'
                }
              }
            },
            series: [{
              name: '数据系列1',
              type: 'line',
              data: [150, 230, 224, 218, 135, 147, 260],
              itemStyle: {
                color: '#5470c6'
              },
              lineStyle: {
                width: 2,
                type: 'solid'
              },
              symbol: 'circle',
              symbolSize: 6,
              showSymbol: true,
              smooth: false
            }]
          }
        },
        CommonTable: {
          columns: [
            { title: '姓名', key: 'name' },
            { title: '年龄', key: 'age' },
            { title: '地址', key: 'address' }
          ],
          data: [
            { name: '张三', age: 18, address: '北京' },
            { name: '李四', age: 22, address: '上海' }
          ]
        },
        CommonForm: {
          title: '表单标题',
          fields: [
            { label: '用户名', type: 'text', placeholder: '请输入用户名' },
            { label: '密码', type: 'password', placeholder: '请输密码' }
          ]
        },
        CommonCard: {
          title: '卡片标题',
          content: '这是卡片内容',
          showFooter: true,
          buttonText: '查看详情'
        },
        CommonFooter: {
          menuItems: [
            { text: '首页', route: '/' },
            { text: '关于我们', route: '/about' },
            { text: '联系我们', route: '/contact' },
            { text: '帮助中心', route: '/help' }
          ],
          menuColor: '#ffffff',           // 默认文字颜色
          menuActiveColor: '#FFD200',     // 选中文字颜色
          menuFontSize: '20px',
          menuBackground: 'transparent',   // 默认背景色
          menuActiveBackground: 'rgba(255, 255, 255, 0.1)', // 选中背景色
          menuBackgroundImage: require('@/assets/images/menu.png'),        // 默认背景图片
          menuActiveBackgroundImage: require('@/assets/images/menuon.png'),  // 选中状态背景图片
          menuWidth: '180px',              // 菜单项宽度
          menuHeight: '46px',             // 菜单项高度
          currentMenu: '首页',            // 默认选中菜单
          backgroundColor: 'unset',
          backgroundImage: require('@/assets/images/footerBox.png'),
          height: '120px',
          zIndex: 1
        },
      }
      return configs[componentName] || {}
    },
    // 更新组件配置
    updateComponentConfig(newConfig) {
      if (this.selectedIndex !== null) {
        console.log('Updating component config:', newConfig); // 打印新配置
        
        // 更组件配置
        const currentItem = this.canvasItems[this.selectedIndex];
        
        // 如果是图表组件，需要特殊处理
        if (currentItem.component === 'CommonChart') {
          this.canvasItems[this.selectedIndex].config = {
            ...currentItem.config,
            ...newConfig,
            dataSourceType: newConfig.dataSourceType || currentItem.config.dataSourceType,
            apiConfig: {
              ...(currentItem.config.apiConfig || {}),
              ...(newConfig.apiConfig || {})
            }
          };
          
          console.log('Updated chart config:', this.canvasItems[this.selectedIndex].config); // 打印更新后的配置
        } else {
          this.canvasItems[this.selectedIndex].config = {
            ...currentItem.config,
            ...newConfig
          };
        }
        
        // 同时更新样式中的 zIndex
        if (newConfig.zIndex !== undefined) {
          this.canvasItems[this.selectedIndex].style = {
            ...this.canvasItems[this.selectedIndex].style,
            zIndex: newConfig.zIndex
          };
        }
        
        this.generateCode();
      }
    },
    // 添加更样的方法
    updateItemStyle(newStyle) {
      if (this.selectedIndex !== null) {
        this.canvasItems[this.selectedIndex].style = {
          ...this.canvasItems[this.selectedIndex].style,
          ...newStyle
        }
        this.generateCode()
      }
    },
    selectCanvas(event) {
      if (event.target === this.$refs.canvasRef) {
        this.selectedIndex = null;
        this.isCanvasSelected = true;
      }
    },
    updateCanvasConfig(newConfig) {
      this.canvasConfig = {
        ...this.canvasConfig,
        ...newConfig
      };
      this.generateCode();
    },
    getBackgroundImage() {
      let bgImage = '';
      
      // 如果启用了网格
      if (this.canvasConfig.gridVisible) {
        bgImage = `linear-gradient(90deg, rgba(255, 255, 255, 0.1) 1px, transparent 1px),
                   linear-gradient(rgba(255, 255, 255, 0.1) 1px, transparent 1px)`;
        
        // 如果有背景图，添加到网格后面
        if (this.canvasConfig.backgroundImage) {
          bgImage = `url(${this.canvasConfig.backgroundImage}), ${bgImage}`;
        }
        
        // 只在 canvasRef 存时设置式
        if (this.$refs.canvasRef) {
          this.$refs.canvasRef.style.backgroundSize = '20px 20px, 20px 20px';
          this.$refs.canvasRef.style.backgroundPosition = '0 0, 0 0';
        }
      } else if (this.canvasConfig.backgroundImage) {
        // 如果只有景图
        bgImage = `url(${this.canvasConfig.backgroundImage})`;
        if (this.$refs.canvasRef) {
          this.$refs.canvasRef.style.backgroundSize = 'cover';
        }
      }
      
      return bgImage;
    },
    // 修改 convertConfigUnits 方法
    convertConfigUnits(config) {
      const convertedConfig = { ...config };
      const canvasWidth = 1920;
      const canvasHeight = 1080;

      // 遍历配置对象的所有属性
      Object.entries(convertedConfig).forEach(([key, value]) => {
        // 处理图片路径
        if (typeof value === 'string' && value.includes('/blog/src/assets/')) {
          convertedConfig[key] = value.replace('/blog/', '');
        }
        // 处理 px 单位转换
        else if (typeof value === 'string' && value.endsWith('px')) {
          const numValue = parseFloat(value);
          // 处理宽度相关的属性
          if (key.toLowerCase().includes('width')) {
            convertedConfig[key] = `${(numValue / canvasWidth * 100).toFixed(2)}vw`;
          }
          // 处理高度相关的属性
          else if (key.toLowerCase().includes('height')) {
            convertedConfig[key] = `${(numValue / canvasHeight * 100).toFixed(2)}vh`;
          }
          // 处理体大小和字间距
          else if (key.toLowerCase().includes('fontsize') || 
                   key.toLowerCase().includes('letterspacing') ||
                   key === 'letterSpacing') {
            convertedConfig[key] = `${(numValue / canvasWidth * 100).toFixed(2)}vw`;
          }
        }
      });

      return convertedConfig;
    },
    handleTabChange(tabInfo) {
      // 这里可以处理与其他组件的联动
      console.log('处理 tab 变化:', tabInfo)
      
      // 例如：更新其他组件的状态
      this.canvasItems.forEach((item, index) => {
        if (item.component === 'OtherComponent') {
          // 更新其他组件的配置
          const newConfig = {
            ...item.config,
            someProperty: tabInfo.value
          }
          this.canvasItems[index].config = newConfig
        }
      })
      
      // 强制更新视图
      this.$forceUpdate()
    },
    calculateSnapGuidelines(currentX, currentY, currentWidth, currentHeight) {
      const guidelines = {
        vertical: [], // 垂直参考线
        horizontal: [] // 水平参考线
      };
      
      // 当前组件的中心线和边界
      const currentCenterX = currentX + currentWidth / 2;
      const currentCenterY = currentY + currentHeight / 2;
      const currentRight = currentX + currentWidth;
      const currentBottom = currentY + currentHeight;

      // 遍历其他组件
      this.canvasItems.forEach((item, index) => {
        if (index === this.draggedItemIndex) return;

        const style = item.style;
        const itemX = parseInt(style.left);
        const itemY = parseInt(style.top);
        const itemWidth = parseInt(style.width);
        const itemHeight = parseInt(style.height);
        
        // 其他组件的中心线和边界
        const itemCenterX = itemX + itemWidth / 2;
        const itemCenterY = itemY + itemHeight / 2;
        const itemRight = itemX + itemWidth;
        const itemBottom = itemY + itemHeight;

        // 检查垂直对齐
        // 左边对齐
        if (Math.abs(currentX - itemX) < this.snapConfig.threshold) {
          guidelines.vertical.push({ pos: itemX, type: 'left' });
        }
        // 右边对齐
        if (Math.abs(currentRight - itemRight) < this.snapConfig.threshold) {
          guidelines.vertical.push({ pos: itemRight, type: 'right' });
        }
        // 中心对齐
        if (Math.abs(currentCenterX - itemCenterX) < this.snapConfig.threshold) {
          guidelines.vertical.push({ pos: itemCenterX, type: 'center' });
        }

        // 检查水平对齐
        // 顶部对齐
        if (Math.abs(currentY - itemY) < this.snapConfig.threshold) {
          guidelines.horizontal.push({ pos: itemY, type: 'top' });
        }
        // 底部对齐
        if (Math.abs(currentBottom - itemBottom) < this.snapConfig.threshold) {
          guidelines.horizontal.push({ pos: itemBottom, type: 'bottom' });
        }
        // 中心对齐
        if (Math.abs(currentCenterY - itemCenterY) < this.snapConfig.threshold) {
          guidelines.horizontal.push({ pos: itemCenterY, type: 'center' });
        }
      });

      return guidelines;
    },
    handleDragOver(event) {
      if (this.draggedItemIndex !== null) {
        const canvasRect = this.canvasRef.getBoundingClientRect();
        // 获取当前画布的缩放比例
        const scale = this.getCanvasScale();

        // 计算原始位置（考虑缩放）
        let x = (event.clientX - canvasRect.left) / scale;
        let y = (event.clientY - canvasRect.top) / scale;

        // 获取当前拖动组件的尺寸
        const currentItem = this.canvasItems[this.draggedItemIndex];
        const currentWidth = parseInt(currentItem.style.width);
        const currentHeight = parseInt(currentItem.style.height);

        // 计算对齐参考线
        const guidelines = this.calculateSnapGuidelines(x, y, currentWidth, currentHeight);
        
        // 应用吸附
        if (guidelines.vertical.length > 0) {
          const nearestVertical = guidelines.vertical.reduce((prev, curr) => 
            Math.abs(curr.pos - x) < Math.abs(prev.pos - x) ? curr : prev
          );
          if (Math.abs(nearestVertical.pos - x) < this.snapConfig.threshold) {
            x = nearestVertical.pos;
            this.snapConfig.isSnapping = true;
          }
        }

        if (guidelines.horizontal.length > 0) {
          const nearestHorizontal = guidelines.horizontal.reduce((prev, curr) => 
            Math.abs(curr.pos - y) < Math.abs(prev.pos - y) ? curr : prev
          );
          if (Math.abs(nearestHorizontal.pos - y) < this.snapConfig.threshold) {
            y = nearestHorizontal.pos;
            this.snapConfig.isSnapping = true;
          }
        }

        // 更新辅助线位置
        this.dragGuideLines.x = x;
        this.dragGuideLines.y = y;
        this.dragGuideLines.visible = true;

        // 更新网格高亮
        const gridSize = 20;
        const gridX = Math.floor(x / gridSize) * gridSize;
        const gridY = Math.floor(y / gridSize) * gridSize;

        this.gridHighlight = {
          x: this.snapConfig.isSnapping ? x : gridX,
          y: this.snapConfig.isSnapping ? y : gridY,
          visible: true
        };

        // 存储当前的参考线，用于渲染
        this.snapConfig.guidelines = [...guidelines.vertical, ...guidelines.horizontal];

        // 实时更新组件位置，使拖动更流畅
        if (this.draggedItemIndex !== null) {
          const currentItem = this.canvasItems[this.draggedItemIndex];
          if (currentItem.component !== 'CommonHeader' && currentItem.component !== 'CommonFooter') {
            this.canvasItems[this.draggedItemIndex].style = {
              ...this.canvasItems[this.draggedItemIndex].style,
              left: `${x}px`,
              top: `${y}px`
            };
          }
        }
      }
    },
    // 添加获取画布缩放比例的方法
    getCanvasScale() {
      // 根据视窗宽度返回对应的缩放比例
      if (window.innerWidth >= 1921) {
        return 0.8;
      } else if (window.innerWidth <= 1200) {
        return 0.3;
      } else if (window.innerWidth <= 1440) {
        return 0.4;
      } else {
        return 0.5;
      }
    },
    async downloadCanvas() {
      try {
        const canvas = this.$refs.canvasRef;
        
        // 保存当前缩放状态
        const currentScale = canvas.style.transform;
        // 临时设置缩放为 1
        canvas.style.transform = 'scale(1)';
        
        // 等待所有图表重新渲染
        const chartComponents = this.canvasItems
          .filter(item => item.component === 'CommonChart')
          .map((item, index) => ({
            ref: this.$refs[`chart${index}`],
            config: item.config
          }));
        
        await Promise.all(chartComponents.map(({ ref, config }) => {
          if (ref && ref[0]) {
            return new Promise(resolve => {
              if (config && config.option) {
                ref[0].chart?.setOption(config.option);
              }
              ref[0].chart?.resize();
              setTimeout(resolve, 300);
            });
          }
          return Promise.resolve();
        }));

        // 使用 html2canvas 捕获画布内容
        const result = await html2canvas(canvas, {
          scale: 1,
          useCORS: true,
          allowTaint: true,
          backgroundColor: this.canvasConfig.backgroundColor || '#053043',
          width: 1920,
          height: 1080,
          logging: false
        });
        
        // 恢复原始缩放
        canvas.style.transform = currentScale;
        
        // 创建下载链接
        const link = document.createElement('a');
        link.download = `canvas-${new Date().getTime()}.png`;
        link.href = result.toDataURL('image/png');
        link.click();
      } catch (error) {
        console.error('下载画布图片失败:', error);
        alert('下载画布图片失败: ' + error.message);
      }
    }
  }
}
</script>

<style scoped>
.code-generator {
  display: flex;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.canvas-container {
  flex: 1;
  height: 100vh;
  background: #f0f0f0;
  overflow: hidden;
  position: relative;
  padding: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.canvas-area {
  width: 1920px;
  height: 1080px;
  position: relative;
  border: 2px solid #1890ff;
  overflow: hidden;
  box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1);
  margin: 0;
  transform-origin: center;
  transform: scale(var(--canvas-scale, 0.5));
  transition: background-color 0.3s;
}

.canvas-item {
  position: absolute;
  cursor: move;
  border: 1px solid transparent;
  user-select: none;
  min-width: 100px;
  min-height: 50px;
  transition: transform 0.2s, opacity 0.2s;
  background: transparent !important;
}

.canvas-item:hover {
  border: 1px dashed #1890ff;
  transform: scale(1.005);
  z-index: 100 !important;
  background: transparent !important;
}

.canvas-item:active {
  cursor: grabbing;
  opacity: 0.7;
}

.item-actions {
  position: absolute;
  top: -20px;
  right: 0;
  display: none;
}

.canvas-item:hover .item-actions {
  display: block;
}

.delete-btn {
  background: #ff4d4f;
  color: white;
  border: none;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  cursor: pointer;
  line-height: 1;
}

.control-panel {
  width: 450px;
  height: 100vh;
  padding: 20px;
  background: #fff;
  overflow-y: auto;
  border-left: 1px solid #ddd;
  box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
  flex-shrink: 0;
}

.components-list {
  margin-bottom: 20px;
}

.component-item {
  padding: 10px;
  margin: 5px 0;
  background: #f0f0f0;
  cursor: move;
  border-radius: 4px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.comp-icon {
  font-size: 1.2em;
}

.component-item:hover {
  background: #e0e0e0;
}

.property-group {
  margin-bottom: 20px;
  padding: 10px;
  background: #f9f9f9;
  border-radius: 4px;
}

.property-group h4 {
  margin: 0 0 10px 0;
  color: #666;
}

.property-item {
  margin: 10px 0;
  display: flex;
  align-items: center;
}

.property-item label {
  width: 80px;
  color: #666;
}

.property-item input {
  flex: 1;
  padding: 4px 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.code-preview {
  margin-top: 20px;
  border-top: 1px solid #eee;
  padding-top: 20px;
}

.preview-content {
  background: #f5f5f5;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 12px;
  white-space: pre-wrap;
  max-height: 300px;
  overflow-y: auto;
}

.generate-btn {
  margin-top: 10px;
  padding: 8px 16px;
  background: #1890ff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  width: 100%;
}

.generate-btn:hover {
  background: #40a9ff;
}

/* 添加滚动条样式 */
.canvas-area::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.canvas-area::-webkit-scrollbar-track {
  background: #f1f1f1;
}

.canvas-area::-webkit-scrollbar-thumb {
  background: #888;
  border-radius: 4px;
}

.canvas-area::-webkit-scrollbar-thumb:hover {
  background: #555;
}

@media (min-width: 1921px) {
  .canvas-area {
    --canvas-scale: 0.8;
  }
}

@media (max-width: 1920px) {
  .canvas-area {
    --canvas-scale: 0.5;
  }
}

@media (max-width: 1440px) {
  .canvas-area {
    --canvas-scale: 0.4;
  }
}

@media (max-width: 1200px) {
  .canvas-area {
    --canvas-scale: 0.3;
  }
}

@media (max-width: 768px) {
  .code-generator {
    flex-direction: column;
  }
  
  .canvas-area {
    width: 100%;
    height: 60vh;
  }
  
  .control-panel {
    width: 100%;
    height: 40vh;
  }
}

/* 预览按钮样式 */
.preview-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 12px;
  background: #1890ff;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 16px;
  transition: all 0.3s ease;
}

.preview-btn:hover {
  background: #40a9ff;
  transform: translateY(-1px);
}

.btn-icon {
  font-size: 18px;
}

/* 模态框样式 */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
  backdrop-filter: blur(4px);
}

.modal-content {
  background: #282c34;
  border: 1px solid #3e4451;
  border-radius: 8px;
  width: 90%;
  max-width: 800px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  animation: modal-in 0.3s ease-out;
}

.modal-header {
  padding: 16px 24px;
  border-bottom: 1px solid #3e4451;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #21252b;
}

.modal-header h3 {
  margin: 0;
  color: #abb2bf;
  font-size: 18px;
}

.close-btn {
  background: none;
  border: none;
  font-size: 24px;
  color: #999;
  cursor: pointer;
  padding: 0;
  line-height: 1;
}

.close-btn:hover {
  color: #666;
}

.modal-body {
  padding: 24px;
  overflow-y: auto;
  flex: 1;
  background: #282c34;
}

.markdown-body {
  font-family: 'Fira Code', Consolas, Monaco, monospace;
  font-size: 14px;
  line-height: 1.6;
  color: #abb2bf;
}

.md-preview {
  border: none !important;
  background: transparent !important;
}

.md-preview :deep(.md-editor-preview-wrapper) {
  padding: 0 !important;
}

.md-preview :deep(.md-editor-preview pre) {
  margin: 0 !important;
  max-height: none !important;
}

/* 完全移除折叠相关的元素 */
.md-preview :deep(.expand-btn),
.md-preview :deep(.fold-btn) {
  display: none !important;
}

/* 确保代码块始终展开 */
.md-preview :deep(.md-editor-preview pre.fold) {
  max-height: none !important;
  overflow: visible !important;
}

.modal-footer {
  padding: 16px 24px;
  border-top: 1px solid #3e4451;
  display: flex;
  justify-content: flex-end;
  background: #21252b;
}

.copy-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  background: #1890ff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s ease;
}

.copy-btn:hover {
  background: #40a9ff;
}

/* 复制成功状态 */
.copy-btn.copied {
  background: #52c41a;
}

@keyframes modal-in {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 代码块样式 */
.md-preview :deep(pre) {
  background: #21252b !important;
  border-radius: 8px;
  padding: 16px !important;
  margin: 0 !important;
  overflow: auto;
}

.md-preview :deep(code) {
  font-family: 'Fira Code', Consolas, Monaco, monospace !important;
  font-size: 14px !important;
  line-height: 1.6 !important;
  tab-size: 2;
}

/* 滚动条样式 */
.md-preview :deep(pre::-webkit-scrollbar) {
  width: 6px;
  height: 6px;
}

.md-preview :deep(pre::-webkit-scrollbar-thumb) {
  background: #4b5263;
  border-radius: 3px;
}

.md-preview :deep(pre::-webkit-scrollbar-track) {
  background: #282c34;
}

.drag-guide-line {
  position: absolute;
  pointer-events: none;
  z-index: 1000;
}

.drag-guide-line.vertical {
  top: 0;
  height: 100%;
  width: 1px;
  background: #1890ff;
  box-shadow: 0 0 2px rgba(24, 144, 255, 0.5);
}

.drag-guide-line.horizontal {
  left: 0;
  width: 100%;
  height: 1px;
  background: #1890ff;
  box-shadow: 0 0 2px rgba(24, 144, 255, 0.5);
}

.grid-highlight {
  position: absolute;
  width: 20px;
  height: 20px;
  background: rgba(24, 144, 255, 0.2);
  border: 1px solid rgba(24, 144, 255, 0.4);
  pointer-events: none;
  z-index: 999;
  transition: transform 0.1s ease-out;
}

/* 可以添加一个微小的动画效果 */
@keyframes grid-highlight-pulse {
  0% {
    background: rgba(24, 144, 255, 0.2);
  }
  50% {
    background: rgba(24, 144, 255, 0.3);
  }
  100% {
    background: rgba(24, 144, 255, 0.2);
  }
}

.grid-highlight {
  animation: grid-highlight-pulse 1s infinite;
}

.snap-guideline {
  position: absolute;
  pointer-events: none;
  z-index: 1001;
  background-color: #ff4d4f;
}

.snap-guideline.vertical {
  width: 1px;
  height: 100%;
  top: 0;
}

.snap-guideline.horizontal {
  height: 1px;
  width: 100%;
  left: 0;
}

/* 添加虚线动画效果 */
@keyframes dash {
  to {
    background-position: 20px 0;
  }
}

.snap-guideline {
  background-image: linear-gradient(
    to right,
    #ff4d4f 50%,
    rgba(255, 77, 79, 0) 50%
  );
  background-size: 10px 1px;
  animation: dash 1s linear infinite;
}
</style> 